package org.example.system.controller;

import io.minio.errors.MinioException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.example.system.common.result.Result;
import org.example.system.model.dto.FileInfo;
import org.example.system.model.dto.TreeFileList;
import org.example.system.service.OssService;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * 文件接口控制器，处理文件相关的请求
 * 包括文件上传、下载、删除等操作
 *
 * @author liuyang
 */
@Tag(name = "07.文件接口")
@RestController
@RequestMapping("/api/v1/files")
@RequiredArgsConstructor
public class FileController {

    private static final String FILE_DELETE_PERMISSION = "sys:file:delete";
    private static final String FILE_DOWNLOAD_PERMISSION = "sys:file:download";

    // 注入OSS服务
    private final OssService ossService;

    /**
     * 处理文件操作结果
     * @param result 文件操作结果
     * @return 封装后的响应结果
     */
    private <T> Result<T> handleFileOperationResult(T result) {
        return Result.success(result);
    }

    /**
     * 文件上传接口
     * @param file 表单文件对象
     * @return 上传结果
     */
    @PostMapping
    @Operation(summary = "文件上传")
    public Result<FileInfo> uploadFile(
            @Parameter(description = "表单文件对象") @RequestParam(value = "file") MultipartFile file) {
        return handleFileOperationResult(ossService.uploadFile(file));
    }

    /**
     * 头像上传接口
     * @param file 表单文件对象
     * @return 上传结果
     */
    @PostMapping("/avatar")
    @Operation(summary = "头像上传")
    public Result<FileInfo> uploadAvatar(
            @Parameter(description = "表单文件对象") @RequestParam(value = "file") MultipartFile file) {
        return handleFileOperationResult(ossService.uploadAvatar(file));
    }

    /**
     * 获取文件列表接口
     * @return 文件列表
     */
    @GetMapping("/list")
    @Operation(summary = "获取文件列表")
    public Result<List<TreeFileList>> getFileList() throws MinioException, NoSuchAlgorithmException, IOException, InvalidKeyException {
        return handleFileOperationResult(ossService.getFileList());
    }

    /**
     * 删除文件接口
     * @param fileName 文件名
     * @return 删除结果
     */
    @DeleteMapping("/delete")
    @Operation(summary = "删除文件")
    @PreAuthorize("@ss.hasPerm('" + FILE_DELETE_PERMISSION + "')")
    public Result<Void> deleteFile(@RequestParam("fileName") String fileName)
            throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        ossService.deleteFile(fileName);
        return Result.success();
    }

    /**
     * 批量删除文件接口
     *
     * @param fileNames 文件名列表
     * @return 删除结果
     */
    @DeleteMapping("/deleteFiles")
    @Operation(summary = "批量删除文件")
    @PreAuthorize("@ss.hasPerm('" + FILE_DELETE_PERMISSION + "')")
    public Result deleteFiles(@RequestBody List<String> fileNames) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        // 调用OSS服务的批量删除文件方法
        ossService.deleteFileBatch(fileNames);
        // 返回删除结果
        return Result.success();
    }

    /**
     * 文件下载接口
     *
     * @param fileName 文件名
     * @return 文件下载响应
     */
    @GetMapping("/downLoadFile")
    @Operation(summary = "文件下载")
    @PreAuthorize("@ss.hasPerm('" + FILE_DOWNLOAD_PERMISSION + "')")
    public ResponseEntity<InputStreamResource> fileDownLoad(@RequestParam("fileName") String fileName) {
        // 调用OSS服务的文件下载方法
        return ossService.downLoadFile(fileName);
    }

    /**
     * 批量文件上传接口
     *
     * @param files 文件列表
     * @return 上传结果
     */
    @PostMapping("/uploadFiles")
    @Operation(summary = "批量文件上传")
    public Result<List<FileInfo>> uploadFiles(@RequestBody List<MultipartFile> files) {
        return handleFileOperationResult(ossService.uploadFiles(files));
    }

    /**
     * 文件打包下载接口
     * @param fileNames 文件名列表
     * @return 文件打包下载响应
     */
    @PostMapping("/downLoadZip")
    @Operation(summary = "文件打包下载")
    public ResponseEntity<byte[]> downLoadZip(@RequestBody List<String> fileNames) {
        return ossService.downLoadFileZip(fileNames);
    }
}